#!/bin/bash

function create_disk
# args: $1 disk_file, $2 disk_size
{
  dd if=/dev/zero of=$1 bs=1000000 count=0 seek=$2000
}

function get_cylinders
# args: $1 size
{
  #FIXME there is a complicated method to calculate C.H.S. this is just a stupid simplify
  expr $1000000000 / \( 512 \* 63 \* 255 \)
}

function init_partition_table
# args: $1 disk_file, $2 dsize
{
  cylinders=$(get_cylinders $2)
  echo there are total $cylinders cylinders in $1
  fdisk -C $cylinders $1 <<EOF
n
p
1


t
b
a
1
w
EOF
}

function format_and_mount
# args: $1 disk
{
  install-mbr $1
  offset_p1=32256       #FIXME this is ugly
  loopdev=$(losetup -f) #FIXME potential race condition here
  MAPPER=`echo $loopdev | sed 's/dev\//&mapper\//'`"p1"
  #losetup -o $offset_p1 $loopdev $1
  losetup $loopdev $1
  kpartx -a $loopdev

  #mkfs.vfat -F 32 $loopdev
  mkfs.vfat -F 32 $MAPPER

  ret=$(mktemp -d)
  mount $MAPPER $ret -t vfat -o shortname=winnt

  # trap umount and free loopdev
  trap "test -e $tmpdir && cleanup $ret" INT TERM EXIT
}

function extract_archive
# args: $1 archive, $2 mount_dir
{
  ## try tar.gz
  tar xvzf $1 -C $2 || return

  ## tar.bz2
  tar xvjf $1 -C $2 || return

  ## try 7z
  7zr x -o$2 $1 || return
}

function install_bootloader
# args: $1 loopdev, $2 mount_dir
{
  syslinux -f $1
  cp /usr/lib/syslinux/chain.c32 $2
  cat > $2/syslinux.cfg <<EOF
default 1
timeout 0
label 1
  kernel chain.c32
  append hd0,1 ntldr=ntldr
EOF
}

function cleanup
# args: $1 mountdir
{
  echo umount $1
  umount $1
  rmdir $1
  echo free $loopdev
  kpartx -d $loopdev
  losetup -d $loopdev
  exit
}

function fixattr
# args: $1 mountdir
{
  #dasdir="$1/Documents and Settings"
  #ls "$dasdir" | xargs -d "\n" -I TheDir echo rm "$dasdir/TheDir/Start Menu/Programs/Startup/desktop.ini"
  #ls "$dasdir" | xargs -d "\n" -I TheDir rm "$dasdir/TheDir/Start Menu/Programs/Startup/desktop.ini"
  $topdir/dosfs_attrib.py $1 load < $1/attributes.dump
}

function change_host_name()
#  args: $1 sysprep_file_path, $2 new_name
{
  sed -i "s/ComputerName=.*/ComputerName=${2}/" $1
}

function valid_ip()
{
  local  ip=$1
  local  stat=1 # invalid
  
  if [[ $1 == "0" ]] ; then
     return 0
  fi
 
  if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
  OIFS=$IFS
  IFS='.'
  ip=($ip)
  IFS=$OIFS
  [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
          && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
  stat=$?
  fi
  return $stat
}

function change_network_conf_bak()
#  args: $1 sysprep_file_path, $2 ip, $3 mask, $4 gateway
{
  sed -i 's/InstallDefaultComponents=.*/InstallDefaultComponents=No/' $1
  sed -i 's/\[sysprepcleanup\]//' $1
  cat >>$1 <<EOF
[NetAdapters]
    Adapter1=params.Adapter1

[params.Adapter1]
    INFID=*

[NetClients]
    MS_MSClient=params.MS_MSClient

[NetProtocols]
    MS_TCPIP=params.MS_TCPIP

[params.MS_TCPIP]
    DNS=No
    UseDomainNameDevolution=No
    EnableLMHosts=Yes
    AdapterSections=params.MS_TCPIP.Adapter1

[params.MS_TCPIP.Adapter1]
    SpecificTo=Adapter1
    DHCP=No
    IPAddress=$2
    SubnetMask=$3
    DefaultGateway=$4
    WINS=No
    NetBIOSOptions=0

[sysprepcleanup]
EOF
}

function change_network_conf()
#  args: $1 sysprep_file_path, $2 ip, $3 mask, $4 gateway $5 dns
{
cat >$1'/interfaces.txt'<<EOF
pushd interface ip\r\nset address name="" source=static addr=$2 mask=$3\r\nset address name="" gateway=$4 gwmetric=0\r\nset dns name="" source=static addr=$5 register=PRIMARY\r\nset wins name="" source=static addr=none\r\npopd
EOF
cat >$1'/Documents and Settings/All Users/Desktop/NetworkConfig.bat'<<EOF
cls\r\n
netsh -f c:\\interfaces.txt\r\n
@echo off
reg add "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ComputerName" /v "ComputerName" /d "$6" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters" /v "NV Hostname" /d "$6" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters" /v "Hostname" /d "$6" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" /v "ComputerName" /d "$6" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v "NV Hostname" /d "$6" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v "Hostname" /d "$6" /f 
EOF
}

function change_hostname_only()
{
cat >$1'/Documents and Settings/All Users/Desktop/NetworkConfig.bat'<<EOF
@echo off
reg add "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ComputerName" /v "ComputerName" /d "$1" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters" /v "NV Hostname" /d "$1" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters" /v "Hostname" /d "$1" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName" /v "ComputerName" /d "$1" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v "NV Hostname" /d "$1" /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v "Hostname" /d "$1" /f 
EOF
}

topdir=$(dirname $0)
if [ $(expr substr $topdir 1 1) != / ] ; then
  topdir=$PWD/$topdir
fi

# show usage
if [ x$1 = x -o x$2 = x -o x$3 == x -o x$4 == x -o x$5 == x ] ; then
  echo Usage: $0 archive_file disk_file disk_size_in_gb host_name network_info[dhcp or ip:mask:gateway]
  exit 1
fi

# test if $1 is the right type
afile=$1
#FIXME no type test
if [ ! -e $afile ] ; then
  echo archive $afile not exist
  exit
fi

# test if $2 is already exist
dfile=$2
if [ -e $dfile ] ; then
  echo disk $dfile already exist
  exit 1
fi

# test if $3 is number and not < 30
dsize=$3
if [ $dsize -lt 30 ]; then
  echo good size $dsize
else
  echo bad size $dsize
  exit 1
fi

hostname=$4

# test if $5 is in valid format
netinfo=$5
dflag=0
if [ $netinfo == 'dhcp' ]; then
   dflag=1
else
   OIFS=$IFS
   IFS=':'
   net=($netinfo)
   IFS=$OIFS

   if [ ${#net[@]} -ne 4 ]; then 
     echo 'network-info can either be "dhcp" or something like "192.168.1.1:255.255.255.0:192.168.1.254" '
     exit 1 
   fi

   if valid_ip ${net[0]}; then
      if [ ${net[0]} == "0" ]; then
         ip=" "
      else
         ip=${net[0]}
      fi     
   else
      echo "IP error."
      exit 1
   fi

   if valid_ip ${net[1]}; then
      if [ ${net[1]} == "0" ]; then
         netmask="255.255.255.0"
      else
         netmask=${net[1]}
      fi
   else
      echo "Netmask error."
      exit 1     
   fi

   if valid_ip ${net[2]}; then
      if [ ${net[2]} == "0" ]; then
         gateway=" "
      else
         gateway=${net[2]}
      fi
   else
      echo "Gateway error."
      exit 1
   fi

   if valid_ip ${net[3]}; then
      if [ ${net[3]} == "0" ]; then
         dnsserver="202.112.128.51"
      else
         dnsserver=${net[3]}
      fi
   else
      echo "dns error."
      exit 1
   fi

fi

# create empty sparse disk at requested size
create_disk $dfile $dsize

# initialize partition table
init_partition_table $dfile $dsize

# format partition 1 as fat32 and mount it
format_and_mount $dfile
tmpdir=$ret

# extract archive in tmpdir
extract_archive $afile $tmpdir
fixattr $tmpdir

#change_host_name $tmpdir'/sysprep/sysprep.inf' $hostname

if [ $dflag -eq 0 ]; then
   echo "configure network ..."
   change_network_conf $tmpdir $ip $netmask $gateway $dnsserver $hostname
else
   change_hostname_only $tmpdir $hostname
fi

# install bootloader to it
install_bootloader $MAPPER $tmpdir

#ls $tmpdir

